MANTA-5522 Add lib/scope-schema.js as the single source of truth for bucket scope schema#11
MANTA-5522 Add lib/scope-schema.js as the single source of truth for bucket scope schema#11cneira wants to merge 13 commits into
Conversation
and MahiClient.prototype.scopeRevoke for immediate key deletion. Both are best-effort with warn-level logging on failure. Single source of truth for per-bucket access key scope constants, validation, and pattern matching. Exported via index.js as scopeSchema. Consumed by sdc-cloudapi directly and by manta-buckets-api via local copy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Match the mahi server endpoint rename. The method name scopeRevoke() is unchanged (JS API, not REST path). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parse and validate opts.scope using scope-schema before sending to the mahi server. Prevents malformed scope strings from poisoning the Redis cache and corrupting authorization decisions for affected access keys. Null/undefined scope (unrestricted key) is still accepted. AI-generated code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove redundant local require('querystring') that shadowed
the module-level qs variable (JSL warning). Strip trailing
whitespace in client.js. Parenthesize typeof expressions in
scope-schema.js per jsstyle.
AI-generated code.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
danmcd
left a comment
There was a problem hiding this comment.
Checkpoint, and I shouldn't revisit here until I've completely looked at TritonDataCenter/mahi#30 .
travispaul
left a comment
There was a problem hiding this comment.
Please bump the version in package.json too
danmcd
left a comment
There was a problem hiding this comment.
Seems okay, but my too-narrow complaint holds here as well. Unsure why Claude emits it like this.
Cover validateScope shape rejection, envelope rejection, per-entry rejection, and success path. Smoke-test isValidBucketPattern, matchBucketPattern, and parseScope.
danmcd
left a comment
There was a problem hiding this comment.
Still too-few-columns in some cases, I think.
| err: err, | ||
| accesskeyid: accesskeyid | ||
| }, 'scopeRevoke: mahi call failed' + | ||
| ' (non-fatal)'); |
There was a problem hiding this comment.
For example, wouldn't this line and the prior on join together so it looks like:
if (err) {
if (self.http.log) {
self.http.log.warn({
err: err,
accesskeyid: accesskeyid
}, 'scopeRevoke: mahi call failed (non-fatal)');
}
| scope: scopeJson, | ||
| error: null | ||
| }); | ||
| return ({valid: true, scope: scopeJson, error: null}); |
There was a problem hiding this comment.
This one actually makes sense to stay on different lines. SOme of the other ones above are more what I had in mind.
| error: 'scope: permissions[' + i + | ||
| '].bucket: invalid characters' + | ||
| ' or wildcard position' | ||
| '].bucket: invalid characters' + ' or wildcard position' |
There was a problem hiding this comment.
Yeah, stuff like this is what I was talking about.
There was a problem hiding this comment.
Also, and I forgot this 3 days ago, you can lose the + and just make it one const string here.
danmcd
left a comment
There was a problem hiding this comment.
Are you missing an export here, or am I missing something I don't understand?
Also more too-narrow code.
| accesskeyid: accesskeyid | ||
| }, 'scopeRevoke: mahi call failed' + | ||
| ' (non-fatal)'); | ||
| }, 'scopeRevoke: mahi call failed' + ' (non-fatal)'); |
There was a problem hiding this comment.
Two const strings don't need to be +-ed.
}, 'scopeRevoke: mahi call failed (non-fatal));
| error: 'scope: permissions[' + i + | ||
| '].bucket: invalid characters' + | ||
| ' or wildcard position' | ||
| '].bucket: invalid characters' + ' or wildcard position' |
There was a problem hiding this comment.
Also, and I forgot this 3 days ago, you can lose the + and just make it one const string here.
| self.http.log.warn({ | ||
| err: err, | ||
| accesskeyid: opts.accesskeyid | ||
| }, 'cachePush: mahi call failed' + |
There was a problem hiding this comment.
This and the following line can be squashed and made one constant string.
|
|
||
| module.exports = { | ||
| MahiClient: MahiClient, | ||
| createClient: function (opts) { |
There was a problem hiding this comment.
This one (cachePush) I need an answer to, and then I'm likely good.
There was a problem hiding this comment.
No, as it's defined as a prototype it will be available when a new MahiClient is instanciated.
danmcd
left a comment
There was a problem hiding this comment.
Cleared up my concerns here over on MANTA-5521. As with others, make sure you get @travispaul to sign-off on this as well.
travispaul
left a comment
There was a problem hiding this comment.
I'm good, I also noticed some const string concatenation but functionally it doesn't make much of a difference so not blocking on it.
cachePush wrote an access-key entry to a single mahi instance on create / update, and scopeRevoke deleted one on key removal. Both pretended to fan-out across the cache pool but only ever reached the single instance the caller resolved by DNS — the SDC mahi pool, never the Manta authcache pool that serves the S3 data plane. They were a single-instance optimisation on the SDC side that the sigv4 read-through (resolves cache misses against UFDS) made irrelevant. cloudapi stopped calling them. Drop both methods from MahiClient. Drop the scope-schema require they pulled in for scope validation (scopeSchema is still exported separately from index.js). External callers of node-mahi that consume cachePush / scopeRevoke will see a method-not-found at runtime; this is a breaking change in the next published version. === AI-METADATA === AI-Tool: Claude Code AI-Model: claude-opus-4-7 AI-Role: refactor / cleanup AI-Confidence: high Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a shared bucket scope validation module and two new endpoints for bucket scoped access keys:
cachePush : Push a key directly to mahi/authcache redis cache, the intent is that the newly created access key can be used right away and bypass UFDS replication delay.
scopeRevoke: Does the opposite, it inmediately deletes a key from the redis cache.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com